package com.mask.share.utils;

import cn.hutool.core.img.ImgUtil;
import org.apache.commons.lang3.StringUtils;
import org.opencv.core.Mat;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.File;
import java.io.IOException;

/**
 * 通过java 实现 图片的工具
 */
public class ImageJavaUtils {
    /**
     * JAVA代码截取图片
     */
    private static BufferedImage 截取图片(String file, int x, int y, int x1, int y1, String saveFile) {
        BufferedImage originalImage = ImgUtil.read(file);
        // 设定裁剪的起始坐标和尺寸
        int width = x1 - x; // 裁剪宽度
        int height = y1 - y; // 裁剪高度

        BufferedImage croppedImage = originalImage.getSubimage(x, y, width, height);

        if (StringUtils.isNotBlank(saveFile)) {
            File outputFile = new File(saveFile);
            ImgUtil.write(croppedImage, outputFile);
        }
        return croppedImage;
    }

    /**
     * 把openCV的Mat 转为 java 使用的BufferedImage
     *
     * @param mat
     * @return
     */
    public static BufferedImage mat2BufferedImage(Mat mat) {
        int type = BufferedImage.TYPE_3BYTE_BGR;

        int width = mat.cols();
        int height = mat.rows();

        // 创建BufferedImage对象
        BufferedImage bufferedImage = new BufferedImage(width, height, type);
        byte[] data = ((DataBufferByte) bufferedImage.getRaster().getDataBuffer()).getData();
        mat.get(0, 0, data);
        return bufferedImage;
    }


    /**
     * {@link ImageJavaUtils#calculateSimilarity(BufferedImage, BufferedImage)}
     */
    public static double calculateSimilarity(String image1Str, String image2Str) {
        // 加载图片
        try {
            BufferedImage image1 = ImageIO.read(new File(image1Str));
            BufferedImage image2 = ImageIO.read(new File(image2Str));
            return calculateSimilarity(image1, image2);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * {@link ImageJavaUtils#calculateSimilarity(BufferedImage, BufferedImage)}
     */
    public static double calculateSimilarity(Mat mat1, Mat mat2) {
        // 加载图片
        BufferedImage image1 = mat2BufferedImage(mat1);
        BufferedImage image2 = mat2BufferedImage(mat2);
        return calculateSimilarity(image1, image2);
    }

    /**
     * 计算两张图片的相似度（基于像素差异）
     *
     * @return 取值范围在0~1.0
     */
    public static double calculateSimilarity(BufferedImage image1, BufferedImage image2) {
        // 检查图片尺寸是否相同
        if (image1.getWidth() != image2.getWidth() || image1.getHeight() != image2.getHeight()) {
            throw new IllegalArgumentException("Images must be of the same size");
        }

        // 计算像素差异
        long diff = 0;
        for (int i = 0; i < image1.getWidth(); i++) {
            for (int j = 0; j < image1.getHeight(); j++) {
                int rgb1 = image1.getRGB(i, j);
                int rgb2 = image2.getRGB(i, j);

                // 计算RGB值的差异（这里简单地取绝对值之和）
                int rDiff = (rgb1 >> 16 & 0xff) - (rgb2 >> 16 & 0xff);
                int gDiff = (rgb1 >> 8 & 0xff) - (rgb2 >> 8 & 0xff);
                int bDiff = (rgb1 & 0xff) - (rgb2 & 0xff);

                diff += Math.abs(rDiff) + Math.abs(gDiff) + Math.abs(bDiff);
            }
        }

        // 计算总像素数
        int totalPixels = image1.getWidth() * image1.getHeight();

        // 计算平均差异（注意：这里除以的是3*255*255*totalPixels来标准化到0-1范围，但更常见的是除以像素总数*255*3然后转换为百分比）
        // 但为了简单起见，我们只计算差异并返回一个相对值，你可以根据需要调整这个值
        double averageDiff = (double) diff / (3 * 255 * totalPixels);

        // 转换为相似度（1 - 平均差异），但注意这里的相似度可能不是非常直观，因为它依赖于差异的计算方式
        double similarity = 1 - averageDiff;

        // 注意：这里的相似度计算可能不是最准确的，因为它没有考虑到颜色分布、亮度等因素
        // 在实际应用中，你可能需要采用更复杂的算法，如直方图比较、结构相似性指数(SSIM)等

        return similarity;
    }

    /**
     * 计算两张图片的相似度（判断多个个像素点相等）
     * 更适合截图。   基于图片的像素点不同判断，如果一个像素点的rgb有任何一个不同，就认为整个点不同。 一般一样就是100%了
     *
     * @return
     * @throws IOException
     */
    public static double calcSimilarity(String image1Str, String image2Str) {
        try {
            // 加载图片
            BufferedImage image1 = ImageIO.read(new File(image1Str));
            BufferedImage image2 = ImageIO.read(new File(image2Str));
            return calcSimilarity(image1, image2);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static double calcSimilarity(BufferedImage image1, BufferedImage image2) {
        // 检查图片尺寸是否相同
        if (image1.getWidth() != image2.getWidth() || image1.getHeight() != image2.getHeight()) {
            throw new IllegalArgumentException("Images must be of the same size");
        }

        // 计算像素差异
        long diff = 0;
        long same = 0;
        for (int i = 0; i < image1.getWidth(); i++) {
            for (int j = 0; j < image1.getHeight(); j++) {
                int rgb1 = image1.getRGB(i, j);
                int rgb2 = image2.getRGB(i, j);

                // 计算RGB值的差异（这里简单地取绝对值之和）
                int rDiff = Math.abs((rgb1 >> 16 & 0xff) - (rgb2 >> 16 & 0xff));
                int gDiff = Math.abs((rgb1 >> 8 & 0xff) - (rgb2 >> 8 & 0xff));
                int bDiff = Math.abs((rgb1 & 0xff) - (rgb2 & 0xff));

                if (rDiff == 0 && gDiff == 0 && bDiff == 0) {
                    same++;
                } else {
                    diff++;
                }
            }
        }

        // 放大差异的像素点
        return 1 - (diff * 1.0 / (diff + same));
    }


}
